// Input.h

#include "memory.h"

#ifndef INPUT_H
#define INPUT_H

#define XINPUT_GAMEPAD_DPAD_UP          0x00000001
#define XINPUT_GAMEPAD_DPAD_DOWN        0x00000002
#define XINPUT_GAMEPAD_DPAD_LEFT        0x00000004
#define XINPUT_GAMEPAD_DPAD_RIGHT       0x00000008
#define XINPUT_GAMEPAD_START            0x00000010
#define XINPUT_GAMEPAD_BACK             0x00000020
#define XINPUT_GAMEPAD_LEFT_THUMB       0x00000040
#define XINPUT_GAMEPAD_RIGHT_THUMB      0x00000080
#define XINPUT_GAMEPAD_LEFT_SHOULDER    0x0100
#define XINPUT_GAMEPAD_RIGHT_SHOULDER   0x0200
#define XINPUT_GAMEPAD_A                0x1000
#define XINPUT_GAMEPAD_B                0x2000
#define XINPUT_GAMEPAD_X                0x4000
#define XINPUT_GAMEPAD_Y                0x8000

#define MAX_CONTROLLERS (4)

class InputManager
{

public:
	enum ControllerButtonMask
	{
		cControllerUp = XINPUT_GAMEPAD_DPAD_UP,
		cControllerDown = XINPUT_GAMEPAD_DPAD_DOWN,
		cControllerLeft = XINPUT_GAMEPAD_DPAD_LEFT,
		cControllerRight = XINPUT_GAMEPAD_DPAD_RIGHT,
		cControllerStart = XINPUT_GAMEPAD_START,
		cControllerBack = XINPUT_GAMEPAD_BACK,
		cControllerLS = XINPUT_GAMEPAD_LEFT_THUMB,
		cControllerRS = XINPUT_GAMEPAD_RIGHT_THUMB,
		cControllerLB = XINPUT_GAMEPAD_LEFT_SHOULDER,
		cControllerRB = XINPUT_GAMEPAD_RIGHT_SHOULDER,
		cControllerA = XINPUT_GAMEPAD_A,
		cControllerB = XINPUT_GAMEPAD_B,
		cControllerX = XINPUT_GAMEPAD_X,
		cControllerY = XINPUT_GAMEPAD_Y
	};
private:

	struct ControllerState
	{
		bool isConnected;
		unsigned char controllerId;

		unsigned int buttonMaskTemp; // Used for SDL to per frame mask event translation

		unsigned int buttonMask; // Current button states
		unsigned int buttonPressedMask; // Buttons that were pressed this frame
		unsigned int buttonReleasedMask; // Buttons that were released this frame

	public:
		// Returns whether the button was pressed this frame
		bool isPressed(ControllerButtonMask _buttonMask) { return (_buttonMask & buttonPressedMask)!=0; }
		
		// Returns whether the button was released this frame
		bool isReleased(ControllerButtonMask _buttonMask) { return (_buttonMask & buttonReleasedMask)!=0; }

		// Returns whether the button is current held down, regardless of frame it was pressed
		bool isDown(ControllerButtonMask _buttonMask) { return (_buttonMask & buttonMask)!=0; }
	};
	ControllerState m_controllerStates[MAX_CONTROLLERS];

public:
	InputManager( );
	~InputManager( );

	void KeyDown( ControllerButtonMask key ) { m_controllerStates[0].buttonMaskTemp |= key; }
	void KeyUp( ControllerButtonMask key ) { m_controllerStates[0].buttonMaskTemp &=~ key; }

	void tick();

	// Returns whether the button was pressed this frame
	bool isPressed(int controller, ControllerButtonMask _buttonMask) { return controller<MAX_CONTROLLERS?m_controllerStates[controller].isPressed(_buttonMask):false; }
	
	// Returns whether the button was released this frame
	bool isReleased(int controller, ControllerButtonMask _buttonMask) { return controller<MAX_CONTROLLERS?m_controllerStates[controller].isReleased(_buttonMask):false; }

	// Returns whether the button is current held down, regardless of frame it was pressed
	bool isDown(int controller, ControllerButtonMask _buttonMask) { return controller<MAX_CONTROLLERS?m_controllerStates[controller].isDown(_buttonMask):false; }

};

extern InputManager inputManager;

#endif /* INPUT_H */